%% Debugging states: For development purposes
Settings.isDebug = false;
Settings.verboseLevel = 1;
Settings.doPlot=1;
Settings.optimise_params=false;
Settings.channelToAnalyze = 1;

Settings.exp.MainDir = '';
Settings.unmixing.unmixPath = '';
Settings.unmixing.unmixCal = '';
Settings.acq.CalibPath = '';
addpath('\\idnas11.d.uzh.ch\cgluec$\documents\GitHub\CHIPS')

%% Settings, Scoresheet, etc.
Settings.exp.ScoreSheetNames = {
    'name.xlsx',...
    };
Settings.exp.ScoreSheetPath = fullfile(Settings.exp.MainDir,Settings.exp.ScoreSheetNames);
  
Settings.unmixing.unmixImg = ...
    'D:\';
Settings.acq.channel = struct('Ca_Memb_Astro', 1, 'blood_plasma', 2);

Settings.exp.BorderROIName = 'B';

% data file suffix
Settings.exp.fnSuffix = '';

%%% Do some checks and generate Paths

SaveFiles{1} = ['ROI_table_', Settings.exp.fnSuffix, '.csv'];% all ROI data
SaveFiles{2} = ['Summary_table_', Settings.exp.fnSuffix, '.csv'];% summary for field of view
SaveFiles{3} = ['test_traces_', Settings.exp.fnSuffix, '.mat'];% normalized 2.5D traces
SaveFiles{4} = ['peak_data', Settings.exp.fnSuffix, '.csv']; %peak data
SaveFiles{5} = ['soma_data', Settings.exp.fnSuffix, '.csv']; %peak data
SaveFiles{6} = ['somataROIs_', Settings.exp.fnSuffix, '.mat'];% CellScans
SaveFiles{7} = ['3DROIs_', Settings.exp.fnSuffix, '.mat'];% CellScans
SaveFiles{8} = ['2p5DROIs_', Settings.exp.fnSuffix, '.mat'];% CellScans

saveDir = fullfile(Settings.exp.MainDir, 'Results');

% Delete results when debugging
if Settings.isDebug
    if exist(saveDir, 'dir')
        rmdir(saveDir, 's')
    end
end

if ~exist(saveDir, 'dir')
    mkdir(saveDir);
end

Settings.exp.saveFiles = fullfile(saveDir, SaveFiles)';

%% Which channel to analyze
Settings.exp.channelToUse = ;

%% Prepare for Spectral unmixing
Settings.unmixing.mixMat = unmix_channels(Settings);

%% Call analysis function
state = pericyte_analysis(Settings)

________________________________________________________________________________

function [FLIKA_3D, somata, FLIKA_2p5D] = actual_analysis(testRoot, Settings, iSpot)

%% load images
expfiles = dir(fullfile(testRoot,'*.tif'));
fnTempList = {expfiles(:).name};
fnList = fullfile(testRoot, fnTempList);

% Create an array of ScanImage Tiffs
ImgArray =  SCIM_Tif(fnList, Settings.acq.channel, Settings.acq.CalFile);

%concatenate trials into single image
ImgArray = RawImg.cat_data(ImgArray(:));

%% Run preprocessing steps
% Spectral Unmixing
ImgArray= ImgArray.unmix_chs(false, [], cell2mat(Settings.unmixing.mixMat));

%% Motion correction
channelToUseMC = Settings.exp.acq.MotionCorrChannel(iSpot); % which channel to use
%channelToUseMC = 2;
NumFrames= size(ImgArray(1,1).rawdata,4);
if Settings.exp.acq.MotionCorrEnd
    %use last 5 frames
    refImg = squeeze(mean(ImgArray(1,1).rawdata(:,:,channelToUseMC, (end-5):end),4));
else
    refImg = squeeze(mean(ImgArray(1,1).rawdata(:,:,channelToUseMC, 5:10),4));
end
ImgArray=ImgArray.motion_correct( 'refImg', refImg,'ch', channelToUseMC,'minCorr', 0.2, 'doPlot', true);

%% Load ImageJ ROIs, make mask
% hand selected ROIs
x_pix= size(ImgArray(1,1).rawdata,2); y_pix= size(ImgArray(1,1).rawdata,1);
scaleF = 1;
% zipPath = 'D:/....';
zipPath= fullfile(testRoot,'RoiSet.zip');
configFindIJ = ConfigFindROIsDummy.from_ImageJ(zipPath, x_pix, y_pix, scaleF);

%% Create Mask from Cell ROI (B)
bIdx = ~cellfun(@isempty, regexp(configFindIJ.roiNames, 'B', 'ONCE')); % look for somata ROI
periMask = configFindIJ.roiMask(:,:,bIdx);

% remove border from IJ mask
configFindIJ.roiMask = configFindIJ.roiMask(:,:,~bIdx);
configFindIJ.roiNames = configFindIJ.roiNames(~bIdx);

%% Create somata mask (S)
% Subtract soma ROIs, update ROIlist
somaMask = configFindIJ.roiMask;
if ndims(somaMask) == 3
    somaMask = any(somaMask, 3);
end

%% 3D Config
% automated selection of ROIs
findConf3D = ConfigFindROIsFLIKA_3D('baselineFrames', 5:50);

% Configs for measuring ROIs
detectConf = ConfigDetectSigsClsfy('propagateNaNs', false, 'excludeNaNs', false,...
    'lpWindowTime', 1, 'spFilterOrder', 6,'spPassBandMin',0.025, 'spPassBandMax', 0.5,...
    'thresholdLP', 15,'thresholdSP', 3.8,'backgroundLevel', 4, 'baselineFrames', 5:50);

% for calculating AUC for each trace
measureConf = ConfigMeasureROIsDummy('baselineFrames', 5:50);
%measureConf = ConfigMeasureROIsZScore();
% Combine the configs into a CellScan config
configCS3D_ROIs = ConfigCellScan(findConf3D, measureConf, ConfigDetectSigsDummy); % pericyte FLIKA, 3D

%% Create CompositeImg CellScan objects
FLIKA_3D = CellScan(fnList, ImgArray, configCS3D_ROIs); % ROIs from 3D FLIKA
FLIKA_3D.channelToUse = Settings.channelToAnalyze;

% do we need a somata celscan or is it enough to have soma rois in the 2p5d
% cs?
% Configs for measuring ROIs
detectConfSoma = ConfigDetectSigsClsfy('propagateNaNs', false, 'excludeNaNs', false,...
    'lpWindowTime', 1, 'spFilterOrder', 6,'spPassBandMin',0.025, 'spPassBandMax', 0.5,...
    'thresholdLP', 30,'thresholdSP', 1.8,'backgroundLevel', 4);
configCSIJ = ConfigCellScan(configFindIJ, measureConf, detectConfSoma); % pericyte hand selected
somata = CellScan(fnList, ImgArray, configCSIJ); % peaks from hand clicked ROIs
somata.channelToUse = Settings.channelToAnalyze;

%% Process 'find'
FLIKA_3D.process(0, 'calcFindROIs');

%% Delete soma from 3D ROIs
% Apply border ROI to Soma mask for overlay
branchMask = periMask;
branchMask(somaMask) = false;

% extract 3D ROIs
tempMask = FLIKA_3D.calcFindROIs.data.roiMask;

% delete rois outside perimeter and inside soma
tempMask = bsxfun(@times, tempMask, branchMask);

somata.process;

%% Do parameter optimisation, if necessary
done = '';
if Settings.optimise_params
    fprintf(['Optimize parameters for somata ROI ', ...
        'measurement and peak detection\n']);
    somata.opt_config();
    while ~(strcmp(lower(done), 'continue'))
        done = string(input('Please type Continue when done and hit enter\n', 's'));
    end
end

% create a new Config
findConfMask = ConfigFindROIsDummy('roiMask', tempMask);

configCS3D_Signals = ConfigCellScan(findConfMask, measureConf, detectConf);

%override old FLIKA_3D
FLIKA_3D = CellScan(fnList, ImgArray, configCS3D_Signals); % ROIs from 3D FLIKA
FLIKA_3D.channelToUse = Settings.channelToAnalyze;
% process again
FLIKA_3D.process;

%%Skip, if 0 ROIs found
FLIKA_3D.process(0, 'calcFindROIs');
if strcmp(FLIKA_3D.calcFindROIs.data.roiNames{1}, 'none')
    warning('No ROIs found in this trial');
else
    FLIKA_3D.process(0, 'calcMeasureROIs');
    FLIKA_3D.process(0, 'calcDetectSigs');
end
%%

%% Do parameter optimisation, if necessary
done = '';
if Settings.optimise_params
    fprintf('Optimize parameters for 3D ROI measurement and peak detection\n');
    FLIKA_3D.opt_config();
    while ~(strcmp(lower(done), 'continue'))
        done = string(input('Please type Continue when done and hit enter\n', 's'));
    end
end

%% Make the debugging plots
% if Settings.doPlot
%     somata(1,1).plot();
%     FLIKA_3D(1,1).plot();
% end

save('-v7.3', Settings.exp.saveFiles{6}, 'somata') % cell scans
save('-v7.3', Settings.exp.saveFiles{7}, 'FLIKA_3D') % cell scans

nStacks = numel(FLIKA_3D);
for iStacks = 1:nStacks
    % Extract the complete mask
    csTemp = FLIKA_3D(iStacks);
    
    roiMask = csTemp.calcFindROIs.data.roiMask;
    cc = bwconncomp(roiMask);
    
    if cc.NumObjects > 0
    
        % Create the 2p5D masks
        nROIs = cc.NumObjects;
        mask2p5D = zeros(size(roiMask, 1), size(roiMask, 2),nROIs);
        for iROI = 1:nROIs
            % Create a 2p5d mask to make it cleaner to measure the ROI
            mask3D_temp = false(size(roiMask));
            mask3D_temp(cc.PixelIdxList{iROI}) = true;
            mask2p5D(:,:,iROI) = any(mask3D_temp, 3);
        end
        
        % Create the configs for only the processes
        config2p5D = ConfigCellScan(ConfigFindROIsDummy(...
            'roiMask', mask2p5D, 'roiNames', ...
            csTemp.calcFindROIs.data.roiNames), ...
            ConfigMeasureROIsDummy(), ...
            ConfigDetectSigsDummy());
        %FLIKA_2p5D(iStacks) = CellScan('', ImgArray(iStacks), config2p5D);
        FLIKA_2p5D(iStacks) = CellScan('', ImgArray(iStacks), config2p5D); % ROIs from 3D FLIKA
        FLIKA_2p5D(iStacks).channelToUse = Settings.channelToAnalyze;
	if nROIs > 0
            FLIKA_2p5D(iStacks) = FLIKA_2p5D(iStacks).process();
        else
        warning('Exclude this file from analysis. No 3D ROIs were found')
    	end
end
%FLIKA_2p5D = FLIKA_2p5D.process();
save('-v7.3', Settings.exp.saveFiles{8}, 'FLIKA_2p5D') % cell scans

 if Settings.doPlot
	try
     somata(1,1).plot();
     FLIKA_3D(1,1).plot();
   %  FLIKA_2p5D(1,1).plot();
	chatch ME
 end
end %end of actual_analysis

_________________________________________________________________________________________

function state = pericyte_analysis(Settings)

%% load scoresheet and loop through animal, spot, etc.
numDrugs = length(Settings.exp.ScoreSheetNames);
All_traces=[];
tblRaw = table();
tblSummary = table();
tblPeak = table();
tblSoma = table();
for iDrug = 1:numDrugs
    
    %read Scoresheet of current animal
    CurrentSheet = Settings.exp.ScoreSheetPath{iDrug};
    Settings = readScoresheet(CurrentSheet, Settings);
    
    % Get SpotID
    spots = Settings.exp.acq.SpotIDs;
    
    for iSpot = 1:length(spots)
        
        %% Extract spot name
        spotId = spots{iSpot};
        
        % Find the idx of paths matching this spot
        CurrentDepth = Settings.exp.acq.Depth(iSpot); %depth
        CurrentCell = Settings.exp.acq.CellType(iSpot); %pericyte type
        CurrentDrug = Settings.exp.acq.Drug(iSpot); %drug treatment
        CurrentAnimal = Settings.exp.acq.AnimalNames{iSpot};
        
        %% Load calibration file
        if strcmp(Settings.exp.acq.Objective(iSpot),'20x')
            %calibration ='E:\matlab\2p-img-analysis\tests\res\calibration_20x.mat';
            calibration = fullfile(Settings.acq.CalibPath, 'calibration_20x.mat');
        else
            calibration = fullfile(Settings.acq.CalibPath, 'calibration_25x_approx.mat');
        end
        Settings.acq.CalFile = CalibrationPixelSize.load(calibration);
        
        %% Get image paths
        testRoot =Settings.exp.acq.LowresPath{iSpot};
        disp(testRoot);
        
        % Spot results path
        SaveFiles{1} = ['somataROIs_', Settings.exp.fnSuffix, '.mat'];% CellScans
        SaveFiles{2} = ['3DROIs_', Settings.exp.fnSuffix, '.mat'];% CellScans
        SaveFiles{3} = ['2p5DROIs_', Settings.exp.fnSuffix, '.mat'];% CellScans
        
        tempPaths = fullfile(testRoot, SaveFiles)';
        if numel(Settings.exp.saveFiles) == 8
            Settings.exp.saveFiles(end-2:end) = tempPaths;
        elseif numel(Settings.exp.saveFiles) == 5
            Settings.exp.saveFiles = [Settings.exp.saveFiles; tempPaths];
        end
        
        if Settings.isDebug
            for i = 5:7
                if exist(Settings.exp.saveFiles{i}, 'file')
                    delete(Settings.exp.saveFiles{i});
                end
            end
        end
        
        if exist(Settings.exp.saveFiles{6},'file') && ...
                exist(Settings.exp.saveFiles{7},'file') && ...
                exist(Settings.exp.saveFiles{8},'file')
            load(Settings.exp.saveFiles{6})
            load(Settings.exp.saveFiles{7})
            load(Settings.exp.saveFiles{8})
        else
            
            % Run CellScan analysis
            [FLIKA_3D, somata, FLIKA_2p5D] = actual_analysis(testRoot, Settings, iSpot);
            
        end

%% Output data
        
        % Prepare some temporary tables for 3D FLIKA and Field of View Summary
        tblTempRaw = table();
        tblTempSummary = table();
        tblTempPeak = table();
        tblTempSoma = table();
        
        % Check if 2p5 is processed ('unprocessed' when no ROIs)
        if strcmp(FLIKA_2p5D.state, 'unprocessed')
            % fill dummy values
            Trace_data=cell(1, 12);
            Trace_data{1,1}= '';
            Trace_data{1,2}= FLIKA_3D.rawImg.name;
            Trace_data{1,4}= spotId;
            Trace_data{1,5}= CurrentAnimal;
            Trace_data{1,6}= CurrentCell;
            Trace_data{1,7}= CurrentDrug;
            Trace_data{1,8} = CurrentDepth(1,1);
            Trace_data{1,10} = [];
            Trace_data{1,11} = [];
            Trace_data{1,12} = FLIKA_2p5D.rawImg.metadata.pixelSize;
            
            nCats = 1;
            tblTempSummary.animalname=repmat({CurrentAnimal}, nCats, 1);
            tblTempSummary.Img = repmat({FLIKA_3D.rawImg.name}, nCats, 1);
            tblTempSummary.Spot=repmat({spotId}, nCats, 1);
            tblTempSummary.celltype=repmat(CurrentCell(1,1), nCats, 1);
            tblTempSummary.Drug=repmat(CurrentDrug(1,1), nCats, 1);
            tblTempSummary.depth=repmat(CurrentDepth(1,1), nCats, 1);

            tblTempSummary.fov_area = repmat(...
                (FLIKA_3D.rawImg.metadata.nPixelsPerLine.* ...
                FLIKA_3D.rawImg.metadata.pixelSize).*2, nCats, 1);
            tblTempSummary.img_duration = repmat(...
                FLIKA_3D.rawImg.metadata.nFrames./ ...
                FLIKA_3D.rawImg.metadata.frameRate, nCats, 1);
            tblTempSummary.num_somas = repmat(nROIs2-1, nCats, 1);
            
            nROIs = 1;
            tblTempRaw.animalname=repmat({CurrentAnimal}, nROIs, 1);
            tblTempRaw.Img = repmat({FLIKA_3D.rawImg.name}, nROIs, 1);
            tblTempRaw.Spot=repmat({spotId}, nROIs, 1);
            tblTempRaw.Drug=repmat(CurrentDrug(1,1), nROIs, 1);
            tblTempRaw.celltype=repmat(CurrentCell(1,1), nROIs, 1);
            tblTempRaw.depth=repmat(CurrentDepth(1,1), nROIs, 1);
            tblTempRaw.ROI = {''};
            %            tblTempRaw.volume = flikaTemp.calcFindROIs.data.volume;
            tblTempRaw.area = 0;
            tblTempRaw.Dis_to_Soma = 0;

else

 % Extract the basic parameters from the 3D FLIKA CellScan
            nROIs = numel(FLIKA_3D.calcFindROIs.data.roiNames);
            tblTempRaw.animalname=repmat({CurrentAnimal}, nROIs, 1);
            tblTempRaw.Img = repmat({FLIKA_3D.rawImg.name}, nROIs, 1);
            tblTempRaw.Spot=repmat({spotId}, nROIs, 1);
            tblTempRaw.Drug=repmat(CurrentDrug(1,1), nROIs, 1);
            tblTempRaw.celltype=repmat(CurrentCell(1,1), nROIs, 1);
            tblTempRaw.depth=repmat(CurrentDepth(1,1), nROIs, 1);
            tblTempRaw.ROI = FLIKA_2p5D.calcFindROIs.data.roiNames;
            %            tblTempRaw.volume = flikaTemp.calcFindROIs.data.volume;
            tblTempRaw.area = FLIKA_2p5D.calcFindROIs.data.area;

% peak data
            tblTempPeak.duration = FLIKA_3D.calcDetectSigs.data.halfWidth;
            tblTempPeak.onset = FLIKA_3D.calcDetectSigs.data.peakStartHalf;
            tblTempPeak.amplitude = FLIKA_3D.calcDetectSigs.data.amplitude;
            tblTempPeak.auc = FLIKA_3D.calcDetectSigs.data.peakAUC;
            tblTempPeak.peakTime = FLIKA_3D.calcDetectSigs.data.peakTime;
            tblTempPeak.peakType = FLIKA_3D.calcDetectSigs.data.peakType;
            tblTempPeak.prominence = FLIKA_3D.calcDetectSigs.data.prominence;
            tblTempPeak.ROI = FLIKA_3D.calcDetectSigs.data.roiName;

 % minimum distance between 3D ROI edge to soma (hand-clicked)
            % 2.5D FLIKA mask
            Dis_to_soma = zeros(nROIs, 1);
            for jROI = 1:nROIs
                tempMask = double(FLIKA_2p5D.calcFindROIs.data.roiMask(:,:,jROI));

                AllSomaDistances=[];
                % somata mask
                nROIs2 = numel(somata.calcFindROIs.data.roiNames);
                for iSoma=1:nROIs2
                    % find soma ROIs
                    if ~isempty(regexp(somata.calcFindROIs.data.roiNames{iSoma,1}, 'S*', 'ONCE')) % look for somata ROI
                        SomaMask = double(somata.calcFindROIs.data.roiMask(:,:,iSoma));
                        [somaDistance,overlap]=minDistance(tempMask,SomaMask); % # of pixels
        AllSomaDistances=vertcat(AllSomaDistances, somaDistance);
                    end

                end
                Dis_to_soma(jROI,1) = min(AllSomaDistances)*FLIKA_3D.rawImg.metadata.pixelSize; % in microns
            end
            tblTempRaw.Dis_to_Soma = Dis_to_soma;

% Extract some summary data
            nCats = 2;
            tblTempSummary.animalname=repmat({CurrentAnimal}, nCats, 1);
            tblTempSummary.Img = repmat({FLIKA_3D.rawImg.name}, nCats, 1);
            tblTempSummary.Spot=repmat({spotId}, nCats, 1);
            tblTempSummary.celltype=repmat(CurrentCell(1,1), nCats, 1);
            tblTempSummary.Drug=repmat(CurrentDrug(1,1), nCats, 1);
            tblTempSummary.depth=repmat(CurrentDepth(1,1), nCats, 1);

            tblTempSummary.fov_area = repmat(...
                (FLIKA_3D.rawImg.metadata.nPixelsPerLine.* ...
                FLIKA_3D.rawImg.metadata.pixelSize).*2, nCats, 1);
            tblTempSummary.img_duration = repmat(...
                FLIKA_3D.rawImg.metadata.nFrames./ ...
                FLIKA_3D.rawImg.metadata.frameRate, nCats, 1);
            tblTempSummary.num_somas = repmat(nROIs2-1, nCats, 1);

 %% extract traces and masks from ROIs.
            traces= FLIKA_2p5D.calcMeasureROIs.data.tracesNorm;

            %preallocate
            Trace_data=cell(size(traces,2),1);
            for iROI = 1:size(traces,2)
                Trace_data{iROI,1}= FLIKA_2p5D.calcFindROIs.data.roiNames{iROI,1};
                Trace_data{iROI,2}= FLIKA_3D.rawImg.name;
                Trace_data{iROI,4}= spotId;
                Trace_data{iROI,5}= CurrentAnimal;
                Trace_data{iROI,6}= CurrentCell;
                Trace_data{iROI,7}= CurrentDrug;
                Trace_data{iROI,8} = CurrentDepth(1,1);
                %Trace_data{iROI,9} = isSoma{iStacks}(iROI);
                Trace_data{iROI,10} = traces(:,iROI);
                Trace_data{iROI,11} = FLIKA_2p5D.calcFindROIs.data.roiMask(:,:,iROI);
                Trace_data{iROI,12} = FLIKA_2p5D.rawImg.metadata.pixelSize;
            end
        end
        nSomaPeaks = numel(somata.calcDetectSigs.data.roiName);
        
        if ~isempty(FLIKA_3D.rawImg.name)
            tblTempSoma.imgName = repmat(FLIKA_3D.rawImg.name, [nSomaPeaks,1]);
        end
        tblTempSoma.spot = repmat({spotId}, [nSomaPeaks,1]);
        tblTempSoma.animal = repmat({CurrentAnimal}, [nSomaPeaks,1]);
        tblTempSoma.cell = repmat({CurrentCell}, [nSomaPeaks,1]);
        tblTempSoma.drug = repmat({CurrentDrug}, [nSomaPeaks,1]);
        tblTempSoma.depth  = repmat(CurrentDepth(1,1), [nSomaPeaks,1]);
        tblTempSoma.area = repmat(somata.calcFindROIs.data.area, [nSomaPeaks,1]);
        
        tblTempSoma.amplitude = somata.calcDetectSigs.data.amplitude;
        tblTempSoma.halfWidth = somata.calcDetectSigs.data.halfWidth;
        tblTempSoma.numPeaks = somata.calcDetectSigs.data.numPeaks;
        tblTempSoma.peakAUC = somata.calcDetectSigs.data.peakAUC;
        tblTempSoma.peakTime = somata.calcDetectSigs.data.peakTime;
        tblTempSoma.peakStartHalf = somata.calcDetectSigs.data.peakStartHalf;
        tblTempSoma.prominence = somata.calcDetectSigs.data.prominence;
        tblTempSoma.roiName = fullfile(somata.calcDetectSigs.data.roiName, spotId);
        
        % update tables
        All_traces=vertcat(All_traces, Trace_data);          
        tblSummary = [tblSummary; tblTempSummary];
        tblRaw = [tblRaw; tblTempRaw];
        tblPeak = [tblPeak; tblTempPeak];
        tblSoma = [tblSoma; tblTempSoma];
                
        clearvars FLIKA_2p5D FLIKA_3D somata traces ll cc roiMask refImg ImgArray tblTempSummary tblTempRaw tblTempSoma
    end
    
end

%% Save all data for R analysis
%cd(fullfile(Settings.exp.MainDir, 'Results'));

% Save the data in 2 csv files, and also as a .mat file
delim = ',';
writetable(tblRaw, Settings.exp.saveFiles{1}, 'Delimiter', delim)  % ROI table
writetable(tblSummary, Settings.exp.saveFiles{2}, 'Delimiter', delim) % summary table
save(Settings.exp.saveFiles{3}, 'All_traces','-v7.3');  % all traces
writetable(tblPeak, Settings.exp.saveFiles{4}, 'Delimiter', delim) % peak data
writetable(tblSoma, Settings.exp.saveFiles{5}, 'Delimiter', delim) % soma data

state = 1;
end % end of pericate_analysis()